﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace ORS.OrderRobot
{
    public static class BackgroundWorkerStartupExtensions
    {
        /// <summary>
        /// 注册实现类
        /// <code>
        /// WebApplication 入口中
        /// await app.Services.BackgroundWorkersRegisterAsync();
        /// </code>
        /// <code>
        ///  控制台 IHost 入口中
        /// await host.Services.BackgroundWorkersRegisterAsync();
        /// </code>
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="configure"></param>
        /// <returns></returns>
        public static async Task BackgroundWorkersRegisterAsync(this IServiceProvider provider,
            Action<IBackgroundWorkerManager>? configure = null)
        {
            using var scope = provider.CreateScope();
            var logger = scope.ServiceProvider.GetRequiredService<ILoggerFactory>().CreateLogger("BackgroundWorkerStartup");
            var manager = scope.ServiceProvider.GetRequiredService<IBackgroundWorkerManager>();
            // 自动注册所有 IBackgroundWorker 实现类
            var allWorkerTypes = AppDomain.CurrentDomain
                .GetAssemblies()
                .Where(a => !a.IsDynamic)
                .SelectMany(a =>
                {
                    try { return a.GetTypes(); }
                    catch { return Array.Empty<Type>(); }
                })
                .Where(t =>
                    typeof(IBackgroundWorker).IsAssignableFrom(t) &&
                    !t.IsInterface &&
                    !t.IsAbstract);

            foreach (var workerType in allWorkerTypes)
            {
                try
                {
                    logger.LogDebug("注册 Worker：{worker}", workerType.FullName);
                    var method = manager.GetType().GetMethod("Register")!;
                    method.MakeGenericMethod(workerType).Invoke(manager, null);
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "注册失败：{worker}", workerType.FullName);
                }
            }

            configure?.Invoke(manager);

            await manager.StartAllAsync();
        }
    }
}
